//
//  XML.m
//
//  Created by Fabio Yasusi Yamamoto <fyy@mac.com> on 08/19/10.
//  Copyright 2010 Appyx. All rights reserved.
//  

#import "XML.h"


@implementation XML
@synthesize doc, element_root, dicXML;

-(id)initWithString:(NSString *)text {
	if (self = [super init]) {
		self.doc = xmlParseMemory([text cStringUsingEncoding:NSUTF8StringEncoding], [text lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
		self.element_root = xmlDocGetRootElement(doc);
		
		
		if( !doc || ! element_root ){
			@throw [NSException exceptionWithName:@"Unable to parser XML" reason:@"Unable to parser XML" userInfo:nil];
		}
		self.dicXML = [self _parseNode:element_root name:nil];
		
	}
	return self;
}
-(NSMutableDictionary *)_parseNode:(xmlNodePtr )node name:(NSString *)name
{
	xmlNodePtr xmlTmp;
	xmlAttr* attr;
	
	NSMutableDictionary * nodeDic = [[NSMutableDictionary alloc] init];
	
	
	if( !node ){
		[nodeDic release];
		return nil;
	}
	if( !name ){
		name = [NSString stringWithUTF8String:(char *)node->name];
		
		node = node->xmlChildrenNode;
	}
	[nodeDic setObject:name forKey:@"name"];
		
		
	if(!node){
		[nodeDic release];
		return nil;		
	}
	attr = node->properties;
	while(attr) {
		xmlChar * ac = xmlGetProp(node, attr->name);
		if( ac ){
			[nodeDic setObject:[NSString stringWithUTF8String:(char *)ac] forKey:[NSString stringWithUTF8String:(char *)attr->name]];				
			
			xmlFree(ac);
		}
		attr = attr->next;
	}
	xmlChar * val = xmlNodeGetContent(node);			
	if( val ){
		[nodeDic setObject:[[NSString stringWithCString:( char *)val encoding:NSUTF8StringEncoding] stringByTrimmingCharactersInSet:[NSCharacterSet  characterSetWithCharactersInString:@" "]] forKey:@"value"];
		xmlFree(val);
	}
	
		
	NSMutableArray * array = [[NSMutableArray alloc] init];
	
	xmlTmp =  node;
	while (xmlTmp) {
		if(xmlTmp->type == XML_ELEMENT_NODE) {
			if( xmlTmp->xmlChildrenNode ){
				NSMutableDictionary * nodeRecursiv = [self _parseNode:xmlTmp->xmlChildrenNode name:[NSString stringWithUTF8String:(char *)xmlTmp->name]];

				if( nodeRecursiv ){
					
					attr = xmlTmp->properties;
					while(attr) {
						xmlChar * ac = xmlGetProp(xmlTmp, attr->name);
						if( ac ){
							[nodeRecursiv setObject:[NSString stringWithUTF8String:(char *)ac] forKey:[NSString stringWithUTF8String:(char *)attr->name]];				
							
							xmlFree(ac);
						}
						attr = attr->next;
					}
					
					[array addObject:nodeRecursiv];
				}
			} else {
				NSMutableDictionary * nodeRecursiv = [[NSMutableDictionary alloc] init];

				[nodeRecursiv setObject:[NSString stringWithUTF8String:(char *)xmlTmp->name] forKey:@"name"];
				bool hasAttr = false;
				
				attr = xmlTmp->properties;
				while(attr) {
					xmlChar * ac = xmlGetProp(xmlTmp, attr->name);
					if( ac ){
						[nodeRecursiv setObject:[NSString stringWithUTF8String:(char *)ac] forKey:[NSString stringWithUTF8String:(char *)attr->name]];				
						
						hasAttr = true;
						xmlFree(ac);
					}
					attr = attr->next;
				}
				
				xmlChar * val = xmlNodeGetContent(xmlTmp);			
				if( val ){
					[nodeRecursiv setObject:[[NSString stringWithCString:( char *)val encoding:NSUTF8StringEncoding] stringByTrimmingCharactersInSet:[NSCharacterSet  characterSetWithCharactersInString:@" "]] forKey:@"value"];
					xmlFree(val);
				}
				if( val || hasAttr ){
					[array addObject:nodeRecursiv];
				}
				[nodeRecursiv release];

			}
				
		}
		
		xmlTmp = xmlTmp->next;
	}
	[nodeDic setObject:array forKey:@"node"];
	[array release];

	return [nodeDic autorelease];
}
-(NSMutableDictionary *)parseDta:(NSString *)string
{
	char * str = (char *)[string UTF8String];
	int valor=0;
	
	for( int i=0;i<[string length];i++){
		if( str[i]=='['){
			str[i]=0x00;
			
			valor = atol( &str[i+1] );
			
			break;
		}
	}
	
	NSMutableDictionary * dic = [[NSMutableDictionary alloc] init];
	[dic setObject:[NSString stringWithUTF8String:str] forKey:@"value"];
	[dic setObject:[NSNumber numberWithInt:valor] forKey:@"pos"];
	
	return [dic autorelease];
	
}
-(id) query:(NSString *)query
{
	NSMutableArray * array = [NSMutableArray arrayWithArray:[query componentsSeparatedByString:@"."]];
	
	id result = nil;
	NSMutableDictionary * currectDic = dicXML;
	bool isValue = false;
	bool isCount = false;
	
	@try{

		if( [[array lastObject] isEqualToString:@"value"] ){
			isValue = true;
			
			[array removeLastObject];
		}
		if( [[array lastObject] isEqualToString:@"count"] ){
			isCount = true;
			
			[array removeLastObject];
		}
		
		for( NSString * dta in array ){
			if( dta == [array lastObject] ){
				
				if( [dta UTF8String][0]=='@' ){
					/* Eh atributo */
					
					return [currectDic objectForKey:[dta substringFromIndex:1]];
					
				} else {
					/* Nao é atributo */
					
					if( isValue ){
						if( strchr( [dta UTF8String],'[' ) ){
							/* Tem index */
							NSMutableDictionary * tmpDic = [self parseDta:dta];
							int pos = [[tmpDic objectForKey:@"pos"] intValue];
							
							currectDic = [[XML getXMLElementArray:[currectDic objectForKey:@"node"]    name:[tmpDic objectForKey:@"value"]] objectAtIndex:pos];
							
							result = [currectDic objectForKey:@"value"];
						} else {
							NSMutableArray * foundArray = [XML getXMLElementArray:[currectDic objectForKey:@"node"]    name:dta];
							currectDic = [foundArray objectAtIndex:0];
							
							result =  [currectDic objectForKey:@"value"];
						}
					} else if( isCount ) {
						NSMutableArray * foundArray = [XML getXMLElementArray:[currectDic objectForKey:@"node"]    name:dta];
						
						if( foundArray ){
							result = [NSNumber numberWithInt:[foundArray count]];
						}
					} else {
						result = [[XML alloc] init];
						[result setDicXML:currectDic];
						
					}
				}
			} else {
				if( strchr( [dta UTF8String],'[' ) ){
					/* Tem index */
					
					NSMutableDictionary * tmpDic = [self parseDta:dta];
					int pos = [[tmpDic objectForKey:@"pos"] intValue];
					
					currectDic = [[XML getXMLElementArray:[currectDic objectForKey:@"node"]    name:[tmpDic objectForKey:@"value"]] objectAtIndex:pos];
				} else {
					currectDic = [XML getXMLElement:[currectDic objectForKey:@"node"]    name:dta];
				}
			}
		}
	}@catch (id theException) {
		result = nil;
		
	}
	
	
	return result;
	
}
+(NSString *)getXMLElementValue:(NSMutableArray *)array name:(NSString *)name
{
	for( int i=0;i<[array count];i++){
		NSMutableDictionary * dic = [array objectAtIndex:i];
		
		if( [[dic objectForKey:@"name"] isEqualToString:name ] ){
			return [dic objectForKey:@"value"];
		}
	}
	return nil;
}
+(NSMutableDictionary *)getXMLElement:(NSMutableArray *)array name:(NSString *)name
{
	for( int i=0;i<[array count];i++){
		NSMutableDictionary * dic = [array objectAtIndex:i];
		
		if( [[dic objectForKey:@"name"] isEqualToString:name ] ){
			return dic;
		}
	}
	return nil;
}
+(NSMutableArray *)getXMLElementArray:(NSMutableArray *)array name:(NSString *)name
{
	NSMutableArray * resarray = [[NSMutableArray alloc] init];
	
	for( int i=0;i<[array count];i++){
		NSMutableDictionary * dic = [array objectAtIndex:i];
		
		if( [[dic objectForKey:@"name"] isEqualToString:name ] ){
			[resarray addObject:dic];
		}
	}
	return [resarray autorelease];
}

+(NSString *)getXMLElementAttribute:(NSMutableArray *)array name:(NSString *)name attribute:(NSString *)attribute
{
	for( int i=0;i<[array count];i++){
		NSMutableDictionary * dic = [array objectAtIndex:i];
		
		if( [[dic objectForKey:@"name"] isEqualToString:name ] ){
			return [dic objectForKey:attribute];
		}
	}
	return nil;
}
+(xmlNodePtr )getElement:(xmlDocPtr )doc  cur:(xmlNodePtr) cur  name:(char *)name
{
    while (cur) {
        if (!(xmlStrcmp(cur->name, (const xmlChar *) name))) {
            return cur;
        }
        cur = cur->next;
    }
    return NULL;
}

@end
